// 1. 最简单的迭代器模式
const myEach = function (arr, fn) {
    for (let i = 0; i < arr.length; i++) {
        fn(i, arr[i])
    }
}
/**
 * 0 1
 * 1 2
 * 2 3
 * 3 4
 * 4 5
 */
myEach([1, 2, 3, 4, 5], (index, value) => {
    console.log(index, value)
})

// 2. es6 中的迭代器
const arr = [1, 2, 3, 4, 5]
// for (let item of arr) {
//     console.log(item)
// }
const it = arr[Symbol.iterator]()
/**
 * { value: 1, done: false }
 * { value: 2, done: false }
 * { value: 3, done: false }
 * { value: 4, done: false }
 * { value: 5, done: false }
 * { value: undefined, done: true }
 */
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())

// 3. 自定义迭代器
// 具备迭代器的数据结构 Array Map Set String TypedArray arguments NodeList
// 类数组的对象
const obj = {
    0: 'a',
    1: 'b',
    2: 'c',
    length: 3,
    [Symbol.iterator]: Array.prototype[Symbol.iterator]
}
for (const objElement of obj) {
    console.log(objElement)
}
// 普通对象
const obj2 = {
    a: 'a',
    b: ['b', 'b'],
    c: 1,
    length: 3,
    [Symbol.iterator]: function () {
        let index = 0
        // 要么保留 this，要么使用 箭头函数 使this 指向 obj2
        const that = this
        return {
            next: function () {
                if (index < that.length) {
                    return {
                        value: that[Object.keys(that)[index++]],
                        done: false
                    }
                } else {
                    return {
                        value: undefined,
                        done: true
                    }
                }
            }
        }
    }
}
for (let obj2Element of obj2) {
    console.log(obj2Element)
}